package com.zxjbyte.yiyi.framework.redis.listener;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.TypeUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.zxjbyte.yiyi.framework.common.util.JsonUtil;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.lang.Nullable;

import java.lang.reflect.Type;

/**
 * Redis Pub/Sub 监听器抽象类，用于实现广播消费
 * @Author zhangxingjia
 * @Date 2023/5/11 11:03
 * @Version: 1.0
 */
public abstract class AbstractMessageListener<T> implements MessageListener {

    // 消息类型
    private final Class<T> messageClazz;

    public AbstractMessageListener(){
        Type typeArgument = TypeUtil.getTypeArgument(getClass());
        Assert.notNull(typeArgument, "Message type needs to be set：[{}]", getClass().getName());
        messageClazz = (Class<T>) TypeUtil.getClass(typeArgument);
    }

    /**
     * 获取Redis Channel
     * @return
     */
    public String getChannel() {
        return this.doChannel();
    }

    @Override
    @SneakyThrows
    public void onMessage(@NotNull Message message, @Nullable byte[] pattern) {
        byte[] body = message.getBody();
        if(ArrayUtil.isEmpty(body)){
            this.doMessage(null);
        } else if(messageClazz.equals(JsonNode.class)){
            T jsonNode = (T) JsonUtil.readTree(body);
            this.doMessage(jsonNode);
        }else {
            T t = JsonUtil.parseObject(body, messageClazz);
            this.doMessage(t);
        }
    }

    /**
     * 处理消息
     *
     * @param message 消息
     */
    public abstract void doMessage(T message);


    /**
     * 处理Redis Channel
     */
    public abstract String doChannel();
}
